<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram 7.1.1</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="800" height="450"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // Style settings
        ctx.lineWidth = 2;
        ctx.font = "italic 20px 'Times New Roman'";
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        // --- Helper function to draw a spring ---
        function drawSpring(ctx, x1, y, x2, num_coils, radius) {
            ctx.beginPath();
            ctx.moveTo(x1, y);
            const wavelength = (x2 - x1) / num_coils;
            for (let i = 0; i < num_coils; i++) {
                let currentX = x1 + i * wavelength;
                ctx.bezierCurveTo(currentX + wavelength / 4, y - radius, currentX + 3 * wavelength / 4, y - radius, currentX + wavelength, y);
                i++;
                if (i >= num_coils) break;
                currentX = x1 + i * wavelength;
                ctx.bezierCurveTo(currentX + wavelength / 4, y + radius, currentX + 3 * wavelength / 4, y + radius, currentX + wavelength, y);
            }
            ctx.stroke();
        }
        
        // Base coordinates and dimensions
        const baseY = 350;
        const wallX = 100;
        const blockWidth = 50;
        const blockHeight = 50;
        const originO_x = 280;
        const distance_l = 250;
        const point_B_x = originO_x + distance_l;
        const height_h = 120;
        const rampEndX = point_B_x + 120;
        const rampEndY = baseY - height_h;

        // 1. Draw Axis and Wall
        ctx.beginPath();
        ctx.moveTo(wallX, baseY - 100);
        ctx.lineTo(wallX, baseY);
        ctx.lineTo(750, baseY);
        ctx.stroke();

        // Arrow for x-axis
        ctx.beginPath();
        ctx.moveTo(750, baseY);
        ctx.lineTo(740, baseY - 5);
        ctx.moveTo(750, baseY);
        ctx.lineTo(740, baseY + 5);
        ctx.stroke();
        ctx.fillText('x', 760, baseY + 15);

        // 2. Draw Spring and related labels
        const springAttachX = originO_x - blockWidth / 2;
        drawSpring(ctx, wallX, baseY - blockHeight/2, springAttachX, 8, 20);
        ctx.fillText('k', (wallX + springAttachX) / 2, baseY - 80);
        
        // Position -x0
        const neg_x0 = 200;
        ctx.beginPath();
        ctx.moveTo(neg_x0, baseY);
        ctx.lineTo(neg_x0, baseY + 10);
        ctx.stroke();
        ctx.fillText('-x₀', neg_x0, baseY + 25);


        // 3. Draw Block at O
        ctx.beginPath();
        ctx.rect(originO_x - blockWidth / 2, baseY - blockHeight, blockWidth, blockHeight);
        ctx.stroke();
        ctx.fillText('m', originO_x, baseY - blockHeight - 20);
        ctx.fillText('O', originO_x, baseY + 20);

        // 4. Draw Ramp and Block at A
        // Point B
        ctx.beginPath();
        ctx.moveTo(point_B_x, baseY);
        ctx.lineTo(point_B_x, baseY + 10);
        ctx.stroke();
        ctx.fillText('B', point_B_x, baseY + 20);
        
        // Curved ramp
        ctx.beginPath();
        ctx.moveTo(point_B_x, baseY);
        ctx.quadraticCurveTo(point_B_x + 40, rampEndY + 10, rampEndX, rampEndY);
        ctx.stroke();
        
        // Block at A
        ctx.beginPath();
        ctx.rect(rampEndX - blockWidth / 2, rampEndY - blockHeight, blockWidth, blockHeight);
        ctx.stroke();
        ctx.fillText('m', rampEndX, rampEndY - blockHeight - 20);
        ctx.fillText('A', rampEndX + blockWidth/2 + 20, rampEndY - blockHeight/2);
        
        // 5. Draw Dimension lines and labels
        // Dimension l
        const dim_l_y = baseY + 40;
        ctx.beginPath();
        ctx.moveTo(originO_x, dim_l_y - 5);
        ctx.lineTo(originO_x, dim_l_y + 5);
        ctx.moveTo(point_B_x, dim_l_y - 5);
        ctx.lineTo(point_B_x, dim_l_y + 5);
        ctx.moveTo(originO_x, dim_l_y);
        ctx.lineTo(point_B_x, dim_l_y);
        ctx.stroke();
        ctx.fillText('l', (originO_x + point_B_x) / 2, dim_l_y + 20);

        // Dimension h
        const dim_h_x = rampEndX + 50;
        ctx.beginPath();
        // Dashed line from A
        ctx.setLineDash([5, 5]);
        ctx.moveTo(rampEndX, rampEndY);
        ctx.lineTo(dim_h_x, rampEndY);
        ctx.stroke();
        ctx.setLineDash([]);
        // Vertical arrow line
        ctx.moveTo(dim_h_x, rampEndY);
        ctx.lineTo(dim_h_x, baseY);
        // Arrowheads
        ctx.moveTo(dim_h_x - 5, rampEndY + 10);
        ctx.lineTo(dim_h_x, rampEndY);
        ctx.lineTo(dim_h_x + 5, rampEndY + 10);
        ctx.moveTo(dim_h_x - 5, baseY - 10);
        ctx.lineTo(dim_h_x, baseY);
        ctx.lineTo(dim_h_x + 5, baseY - 10);
        ctx.stroke();
        ctx.fillText('h', dim_h_x + 15, (rampEndY + baseY) / 2);
        
        // 6. Draw Caption
        ctx.font = "24px 'KaiTi'"; // Using a Chinese font like KaiTi for the caption
        ctx.fillText('力图 7.1.1', canvas.width / 2, baseY + 80);

    </script>
</body>
</html>